/*
 * Copyright 2010-2011 WebEqua Team
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.mathcloud.math.core.matlab.quantity;

//import classes slf4j
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//import classes org.webequa.core
import org.webequa.core.common.quantity.QuantityObject;
import org.webequa.core.common.quantity.RealMatrix;
import org.webequa.core.common.quantity.RealNumber;
import org.webequa.core.generic.signature.GenericQuantityObjectSignature;

//import classes com.mathworks.toolbox.javabuilder
import com.mathworks.toolbox.javabuilder.MWClassID;
import com.mathworks.toolbox.javabuilder.MWComplexity;
import com.mathworks.toolbox.javabuilder.MWNumericArray;

public class MatlabRealMatrix extends MatlabQuantityObject implements RealMatrix
{	
	public MatlabRealMatrix(Integer rows,Integer cols)
	{
		super();
		try
		{
			int []dims = {rows, cols};
			mtlbObject = MWNumericArray.newInstance(dims, MWClassID.DOUBLE, MWComplexity.REAL);
			log.info("{}={}",mtlbVarName,mtlbObject.toString());
			signature = GenericQuantityObjectSignature.getRealMatrixSignature();
			((GenericQuantityObjectSignature)signature).setDimensions(mtlbObject.getDimensions());
			signature.setRealizationName("matlab");
		} catch (Exception e)
		{
			log.error("Exception:",e);
		}
	}
	
	public MatlabRealMatrix(double[][] arg0)
	{
		super();		
		try
		{
			mtlbObject = new MWNumericArray(arg0);
			log.info("{}={}",mtlbVarName,mtlbObject.toString());
			signature = GenericQuantityObjectSignature.getRealMatrixSignature();
			((GenericQuantityObjectSignature)signature).setDimensions(mtlbObject.getDimensions());
			signature.setRealizationName("matlab");
		} catch (Exception e)
		{
			log.error("Exception",e);
		}
	}
	
	public MatlabRealMatrix(RealMatrix arg0)
	{
		super();
		if (arg0!=null)
		{
			try {
			if (arg0.getSignature().getRealizationName().equalsIgnoreCase("matlab"))
			{
				log.debug("Signatures of objects is equivalent");
				mtlbObject = (MWNumericArray) ((MatlabRealMatrix)arg0).getMatlabObject().clone();
				log.info("{}={}",mtlbVarName,((MatlabRealMatrix)arg0).getVarName());	
			}
			else
			{
				log.debug("Signatures of objects isn't equivalent");
				int []dims = {arg0.getNumberOfRows(), arg0.getNumberOfCols()};
				mtlbObject = MWNumericArray.newInstance(dims, MWClassID.DOUBLE, MWComplexity.REAL);
				for (int i=0; i<dims[0]; i++)
					for (int j=0; j<dims[1]; j++)
						setMatrixElement((RealNumber)arg0.getMatrixElement(i, j), i, j);
			}				

			signature = GenericQuantityObjectSignature.getRealMatrixSignature();
			((GenericQuantityObjectSignature)signature).setDimensions(mtlbObject.getDimensions());
			signature.setRealizationName("matlab");
			
			} catch (Exception e)
			{
				log.error("Exception",e);
			}
			}		
		else 
		{	
			log.warn("The object RealMatrix isn't defined");
		}
	}
	
	public int getNumberOfRows()
	{
		if (mtlbObject!=null) {
			return mtlbObject.getDimensions()[0];
		}
	  	else {
	  	  	log.warn("The object isn't defined");
	  	  	}
		return 0;
	}
	
	public int getNumberOfCols()
	{
		if (mtlbObject!=null) {
			return mtlbObject.getDimensions()[1];
		}
	  	else {
	  	  	log.warn("The object isn't defined");
	  	  	}
		return 0;
	}
	
	public QuantityObject getMatrixElement(int i, int j)
	{
		if (mtlbObject!=null)
		{
			if (i<getNumberOfRows() && 
				j<getNumberOfCols() && 
				i>=0 				&& 
				j>=0 )
			{	int []dims = {i+1, j+1};
				return new MatlabRealNumber(((MWNumericArray)mtlbObject).getDouble(dims));
			}  		
			else {
				log.warn("Attempt to use an index({},{}) that is less than zero or greater than or equal to the length of the Matrix",i,j);
			}
		}
		else {
			log.warn("The object isn't defined");
		}
  	return null;
  }
	
	@Override
	public void setMatrixElement(RealNumber arg0, int i, int j)
	{
		if ((mtlbObject!=null) && (arg0!=null))
		{  		
			if (i<=getNumberOfRows() 	&&
				j<=getNumberOfCols() 	&&
				i>=0					&&
				j>=0)
			{
				try
				{
					int []dims = {i+1, j+1};
					((MWNumericArray)mtlbObject).set(dims, arg0.getValue());
					log.info("{}("+i+","+j+")={}",mtlbVarName, arg0.getValue());

				} catch (Exception e)
				{
					log.error("Exception",e);
				}  				
			}
			else {
				log.warn("Attempt to use an index({},{}) that is less than zero or greater than or equal to the length of the Matrix",i,j);
			}
		}	
		else {
			log.warn("One of objects isn't defined");
		}
	}
	
	private static final Logger log = LoggerFactory.getLogger(MatlabRealMatrix.class);	
}
